1 /***
2 * SMClassLoader -
3 *
4 * This class extends the ClassLoader provided
5 * by the BCEL project.
6 *
7 * It instruments the code loaded with the implementation
8 * of the StateMachine provided here.
9 */
10
11 package junit.quilt.cover.state;
12
13 import java.io.*;
14
15 import java.net.URL;
16
17 import java.util.Set;
18 import java.util.List;
19 import java.util.ArrayList;
20 import java.util.Map;
21 import java.util.HashMap;
22 import java.util.HashSet;
23 import java.util.Iterator;
24 import java.util.Collection;
25 import java.lang.ClassLoader;
26
27 // import java.lang.reflect.Constructor;
28
29 import junit.quilt.cover.generic.*;
30
31 import org.apache.bcel.generic.*;
32 import org.apache.bcel.classfile.*;
33 import org.apache.bcel.Constants;
34
35 import org.apache.commons.graph.*;
36
37 public class SMClassLoader
38 extends MethInstClassLoader
39 {
40 private StateMachineRegistry registry = null;
41
42 protectedSMClassLoader( String packages[],/index.html"> SMClassLoader( String packages[],
43 URL path[],
44 ClassLoader parent,
45 StateMachineRegistry registry ) {
46 super( packages, path, parent );
47 this.registry = registry;
48 }
49
50 public void instrumentPool(InstContext context)
51 {
52 ConstantPoolGen pool = context.getConstantPoolGen();
53
54 int visitRef
55 = pool.addMethodref(
56 "junit/quilt/cover/state/SimpleStateMachine",
57 "visit",
58 "(I)V");
59
60 int startRef
61 = pool.addMethodref(
62 "junit/quilt/cover/state/SimpleStateMachine",
63 "start",
64 "()V" );
65
66 context.put( "visitRef", new Integer( visitRef ));
67 context.put( "startRef", new Integer( startRef ));
68 }
69
70 public void instrumentMethod( InstContext context,
71 ControlFlowGraph cfg ) {
72 ClassGen clazz = context.getClassGen();
73
74 // Initialize some variables. . .
75 int startRef = ((Integer) context.get("startRef")).intValue();
76 int visitRef = ((Integer) context.get("visitRef")).intValue();
77 int fieldVar = cfg.makeNewLocal("MSM",
78 new ObjectType("junit.quilt.cover.state.SimpleStateMachine"));
79
80 int numVertices = cfg.getVertices().size() + 4;
81 SimpleStateMachine ssm = new SimpleStateMachine( clazz.getFileName(),
82 numVertices);
83 int fieldRef = addStaticField( context,
84 new ObjectType("junit.quilt.cover.state.SimpleStateMachine"),
85 ssm);
86
87 // Add Initialization Code
88 junit.quilt.cover.state.InitVertex init =
89 new junit.quilt.cover.state.InitVertex(fieldVar,
90 fieldRef,
91 startRef);
92
93 BlockVertex start = cfg.getStartVertex();
94 cfg.setStartVertex( init );
95
96 FlowControlEdge initEdge =
97 getEdgeFactory().makeNormalEdge( init, start );
98 cfg.addEdge( initEdge );
99
100 // Add the Visit code
101 Set blockSet = cfg.getVertices();
102 Vertex blocks[] = (Vertex []) blockSet.toArray( new Vertex[ blockSet.size() ]);
103
104 Map labels = new HashMap(); // BLOCK X INDEX
105 for (short i = 0; i < blocks.length; i++) {
106 BlockVertex bv = (BlockVertex) blocks[i];
107
108 if ((bv != cfg.getStartVertex()) &&
109 (bv != cfg.getEndVertex()) &&
110 (!(bv instanceof CallVisitVertex)) ) {
111 labels.put( bv, new Integer( i ));
112 ssm.addState( i, bv );
113
114 Iterator edges = new HashSet( cfg.getEdges() ).iterator();;
115 while (edges.hasNext()) {
116 FlowControlEdge cEdge = (FlowControlEdge) edges.next();
117 if (cfg.getSource( cEdge ) == bv) {
118 // Edge leads away. . .
119 Vertex target = cfg.getTarget(cEdge);
120 if (labels.containsKey( target )) {
121 int iTarget =
122 ((Integer) labels.get(target)).intValue();
123 ssm.addTransition( i, iTarget );
124 }
125 } else {
126 // Edge leads in . . .
127 Vertex source = cfg.getSource(cEdge);
128 if (! ((cfg.getSource(cEdge) instanceof CallVisitVertex) ||
129 (cfg.getTarget(cEdge) instanceof CallVisitVertex))) {
130 if (labels.containsKey( source )) {
131 int iSource =
132 ((Integer) labels.get(source)).intValue();
133 ssm.addTransition( iSource, i );
134 }
135 instrumentEdge( context, cfg, cEdge,
136 new CallVisitVertex( fieldVar, visitRef, i ));
137 }
138 }
139 }
140 }
141 }
142
143 // Write the StateMachine to the StateMachineRegistry
144 registry.bind( clazz.getClassName(),
145 cfg.getMethodName(),
146 ssm );
147 }
148
149 }
This page was automatically generated by Maven